"""
CAD图审查专家代理 - 负责审查CAD图是否大致完成要求
"""

from typing import Dict, List, Any, Optional
import time
import base64
from pathlib import Path
from loguru import logger

from .base_agent import BaseAgent, AgentResult, ReviewItem
from ..utils.data_loader import ProcessingElement


class CADReviewAgent(BaseAgent):
    """CAD图审查专家代理"""
    
    def __init__(self, api_client, config: Dict[str, Any]):
        super().__init__(
            name="CAD图审查专家",
            agent_type="cad_review",
            api_client=api_client,
            config=config
        )
    
    def get_system_prompt(self) -> str:
        """获取系统提示词"""
        return """你是CAD图纸审查专家，负责审查城市更新方案中的CAD图纸质量。

审查重点和评分标准：
- 图纸完整性（20分）：必要的图纸是否齐全，图纸内容是否完整
- 标注规范性（20分）：尺寸标注、文字说明、符号使用是否规范
- 比例准确性（15分）：图纸比例是否正确和一致，缩放是否合理
- 设计合理性（20分）：设计方案是否合理可行，布局是否优化
- 技术规范性（15分）：是否符合相关技术标准和规范要求
- 图纸一致性（10分）：各图纸之间信息是否一致，无矛盾

评分依据：
- 每个检查项目根据问题严重程度扣分：critical(-5分)，major(-3分)，minor(-1分)
- confidence值基于图纸清晰度、检查覆盖度和问题识别准确性计算
- 总分100分，各项得分累加后计算最终评分

输出JSON格式：
{
    "findings": [
        {
            "item_id": "cad_001",
            "category": "CAD图纸",
            "severity": "critical/major/minor/info",
            "description": "具体问题描述",
            "suggestion": "改进建议",
            "drawing_type": "图纸类型",
            "location": "问题位置",
            "confidence": 0.9,
            "score_impact": "对评分的影响（扣分值）",
            "check_item": "检查项目（完整性/标注规范/比例准确/设计合理/技术规范/图纸一致）"
        }
    ],
    "summary": "CAD图纸整体评估摘要",
    "drawing_analysis": {
        "total_drawings": "图纸总数",
        "drawing_types": ["识别的图纸类型"],
        "completeness": "完整性评估",
        "quality": "质量评估"
    },
    "scoring_details": {
        "completeness_score": "图纸完整性得分（0-20）",
        "annotation_score": "标注规范性得分（0-20）",
        "scale_score": "比例准确性得分（0-15）",
        "design_score": "设计合理性得分（0-20）",
        "technical_score": "技术规范性得分（0-15）",
        "consistency_score": "图纸一致性得分（0-10）",
        "total_score": "总分（0-100）",
        "score_breakdown": "详细扣分说明"
    }
}"""
    
    def process(self, data: Any, context: Dict[str, Any] = None) -> AgentResult:
        """处理数据并返回CAD图审查结果"""
        start_time = time.time()
        
        if not self.validate_input(data):
            return self.handle_api_error(
                Exception("输入数据无效"), 
                "CAD图审查"
            )
        
        try:
            # 提取图像数据
            image_data = self._extract_image_data(data)
            
            if not image_data:
                return self.create_result(
                    success=True,
                    findings=[],
                    summary="无CAD图纸需要审查",
                    confidence=1.0,
                    processing_time=time.time() - start_time
                )
            
            self.log_processing_start(f"CAD图审查，图纸数量: {len(image_data)}")
            
            # 处理所有图像
            all_review_items = []
            drawing_analysis = {
                "total_drawings": len(image_data),
                "drawing_types": [],
                "completeness": "",
                "quality": ""
            }
            
            for i, image_info in enumerate(image_data):
                try:
                    # 审查单个图纸
                    review_items = self._review_single_drawing(image_info, i, context)
                    all_review_items.extend(review_items)
                    
                    # 分析图纸类型
                    drawing_type = self._identify_drawing_type(image_info)
                    if drawing_type and drawing_type not in drawing_analysis["drawing_types"]:
                        drawing_analysis["drawing_types"].append(drawing_type)
                        
                except Exception as e:
                    logger.error(f"审查图纸 {i} 失败: {e}")
                    all_review_items.append(self.create_review_item(
                        item_id=f"cad_error_{i}",
                        category="处理错误",
                        severity="major",
                        description=f"图纸 {i} 处理失败: {str(e)}",
                        suggestion="请检查图纸格式和质量"
                    ))
            
            # 评估整体完整性和质量
            drawing_analysis["completeness"] = self._assess_completeness(drawing_analysis["drawing_types"])
            drawing_analysis["quality"] = self._assess_quality(all_review_items)
            
            # 生成结果
            processing_time = time.time() - start_time
            findings = self.format_findings(all_review_items)
            summary = self.generate_summary(all_review_items)
            confidence = self.calculate_confidence(all_review_items)
            
            self.log_processing_end(True, processing_time, len(findings))
            
            return self.create_result(
                success=True,
                findings=findings,
                summary=summary,
                confidence=confidence,
                processing_time=processing_time,
                metadata={
                    "total_drawings": len(image_data),
                    "drawing_analysis": drawing_analysis,
                    "agent_type": self.agent_type
                }
            )
            
        except Exception as e:
            return self.handle_api_error(e, "CAD图审查")
    
    def _extract_image_data(self, data: Any) -> List[Dict[str, Any]]:
        """提取图像数据"""
        image_data = []
        
        def _is_base64_data(content: str) -> bool:
            """检查内容是否为base64数据"""
            if not content:
                return False
            # 检查是否为data URL格式
            if content.startswith('data:image/'):
                return True
            # 检查是否为纯base64数据（常见的图像格式开头）
            if content.startswith('/9j/') or content.startswith('iVBORw0KGgo') or content.startswith('R0lGOD'):
                return True
            # 检查是否为base64字符串（长度大于100且只包含base64字符）
            if len(content) > 100 and all(c in 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=' for c in content):
                return True
            return False
        
        def _process_image_item(content: str, element_id: str, metadata: dict) -> dict:
            """处理单个图像项，正确区分base64数据和文件路径"""
            if _is_base64_data(content):
                return {
                    'file_path': None,
                    'base64_data': content,
                    'element_id': element_id,
                    'metadata': metadata,
                    'is_base64': True
                }
            else:
                return {
                    'file_path': content,
                    'base64_data': None,
                    'element_id': element_id,
                    'metadata': metadata,
                    'is_base64': False
                }
        
        if isinstance(data, list):
            for item in data:
                if isinstance(item, ProcessingElement):
                    # 检查是否为图像类型
                    if (hasattr(item, 'subcategory') and item.subcategory == 'figure') or \
                       (hasattr(item, 'category') and item.category == 'image') or \
                       (hasattr(item, 'source_type') and item.source_type == 'image') or \
                       (hasattr(item, 'metadata') and item.metadata and 
                        (item.metadata.get('element_type') == 'Image' or
                         item.metadata.get('file_path', '').lower().endswith(('.png', '.jpg', '.jpeg', '.gif', '.bmp', '.tiff', '.svg')))):
                        
                        content = item.content or (item.metadata.get('file_path', '') if item.metadata else '')
                        image_data.append(_process_image_item(content, item.element_id, item.metadata))
                        
                elif isinstance(item, dict):
                    # 检查字典格式的数据
                    if (item.get('subcategory') == 'figure') or \
                       (item.get('category') == 'image') or \
                       (item.get('source_type') == 'image') or \
                       (item.get('metadata', {}).get('element_type') == 'Image') or \
                       'file_path' in item or 'content' in item:
                        
                        # 对于字典数据，需要适配现有结构
                        content = item.get('content') or item.get('file_path', '')
                        if _is_base64_data(content):
                            item['base64_data'] = content
                            item['file_path'] = None
                            item['is_base64'] = True
                        else:
                            item['file_path'] = content
                            item['base64_data'] = None
                            item['is_base64'] = False
                        image_data.append(item)
                        
        elif isinstance(data, ProcessingElement):
            # 单个ProcessingElement对象
            if (hasattr(data, 'subcategory') and data.subcategory == 'figure') or \
               (hasattr(data, 'category') and data.category == 'image') or \
               (hasattr(data, 'source_type') and data.source_type == 'image') or \
               (hasattr(data, 'metadata') and data.metadata and 
                (data.metadata.get('element_type') == 'Image' or
                 data.metadata.get('file_path', '').lower().endswith(('.png', '.jpg', '.jpeg', '.gif', '.bmp', '.tiff', '.svg')))):
                
                content = data.content or (data.metadata.get('file_path', '') if data.metadata else '')
                image_data.append(_process_image_item(content, data.element_id, data.metadata))
                
        elif isinstance(data, dict):
            # 单个字典对象
            if (data.get('subcategory') == 'figure') or \
               (data.get('category') == 'image') or \
               (data.get('source_type') == 'image') or \
               (data.get('metadata', {}).get('element_type') == 'Image') or \
               'file_path' in data or 'content' in data:
                
                content = data.get('content') or data.get('file_path', '')
                if _is_base64_data(content):
                    data['base64_data'] = content
                    data['file_path'] = None
                    data['is_base64'] = True
                else:
                    data['file_path'] = content
                    data['base64_data'] = None
                    data['is_base64'] = False
                image_data.append(data)
        
        return image_data
    
    def _review_single_drawing(self, image_info: Dict[str, Any], index: int, context: Dict[str, Any] = None) -> List[ReviewItem]:
        """审查单个图纸"""
        file_path = image_info.get('file_path', '')
        base64_data = image_info.get('base64_data', '')
        is_base64_image = image_info.get('is_base64', False)
        
        logger.debug(f"🎨 CAD代理开始审查图纸 {index}:")
        logger.debug(f"   File path: {file_path[:100] if file_path else 'None'}...")
        logger.debug(f"   Base64 data length: {len(base64_data) if base64_data else 0}")
        logger.debug(f"   Is base64: {is_base64_image}")
        logger.debug(f"   Image info keys: {list(image_info.keys())}")
        
        # 验证图像数据
        if is_base64_image:
            if not base64_data:
                logger.error(f"   ❌ Base64数据为空")
                return [self.create_review_item(
                    item_id=f"cad_missing_{index}",
                    category="文件问题",
                    severity="critical",
                    description="图纸base64数据为空",
                    suggestion="请检查图纸数据完整性"
                )]
            
            logger.debug(f"   ✅ Base64数据有效，长度: {len(base64_data)}")
            
            # 验证base64数据格式
            if not base64_data.startswith('data:image/'):
                logger.debug(f"   Base64数据不包含MIME类型，添加默认类型")
                # 如果没有MIME类型前缀，添加默认的
                if base64_data.startswith('/9j/'):
                    base64_data = f"data:image/jpeg;base64,{base64_data}"
                elif base64_data.startswith('iVBORw0KGgo') or base64_data.startswith('R0lGOD'):
                    base64_data = f"data:image/png;base64,{base64_data}"
                else:
                    base64_data = f"data:image/jpeg;base64,{base64_data}"
        else:
            if not file_path:
                logger.error(f"   ❌ 文件路径为空")
                return [self.create_review_item(
                    item_id=f"cad_missing_{index}",
                    category="文件问题",
                    severity="critical",
                    description="图纸文件路径为空",
                    suggestion="请检查图纸文件路径"
                )]
            
            logger.debug(f"   检查文件路径是否存在: {file_path}")
            # 如果不是base64数据，检查文件是否存在
            if not Path(file_path).exists():
                logger.error(f"   ❌ 图纸文件不存在: {file_path}")
                return [self.create_review_item(
                    item_id=f"cad_missing_{index}",
                    category="文件问题",
                    severity="critical",
                    description=f"图纸文件不存在或路径无效: {file_path}",
                    suggestion="请检查图纸文件路径"
                )]
            logger.debug(f"   ✅ 文件存在，大小: {Path(file_path).stat().st_size} bytes")
        
        try:
            # 构建图纸审查提示
            prompt = self._build_cad_review_prompt(image_info, context)
            logger.debug(f"   审查提示长度: {len(prompt)} 字符")
            
            # 调用视觉模型进行图纸分析
            logger.debug(f"   🚀 调用视觉模型进行审查...")
            if is_base64_image:
                # 对于base64图像，提取纯base64部分
                if base64_data.startswith('data:image/'):
                    pure_base64 = base64_data.split(',', 1)[1] if ',' in base64_data else base64_data
                else:
                    pure_base64 = base64_data
                
                logger.debug(f"   使用base64数据，纯base64长度: {len(pure_base64)}")
                response = self.api_client.vision_completion(
                    text_prompt=prompt,
                    image_base64=pure_base64,
                    system_prompt=self.get_system_prompt(),
                    model=self.config.get('vision_model', 'THUDM/GLM-4.1V-9B-Thinking')
                )
            else:
                logger.debug(f"   使用文件路径: {file_path}")
                response = self.api_client.vision_completion(
                    text_prompt=prompt,
                    image_path=file_path,
                    system_prompt=self.get_system_prompt(),
                    model=self.config.get('vision_model', 'THUDM/GLM-4.1V-9B-Thinking')
                )
            
            logger.debug(f"   ✅ 视觉模型响应成功，长度: {len(response)} 字符")
            
            # 解析响应
            review_items = self.parse_llm_response(response)
            logger.debug(f"   解析得到 {len(review_items)} 个审查项")
            
            # 为每个审查项添加图纸信息
            for item in review_items:
                if hasattr(item, 'metadata'):
                    item.metadata = item.metadata or {}
                    item.metadata.update({
                        'drawing_index': index,
                        'file_path': file_path if not is_base64_image else None,
                        'base64_data_length': len(base64_data) if is_base64_image else 0,
                        'element_id': image_info.get('element_id', ''),
                        'is_base64': is_base64_image
                    })
            
            return review_items
            
        except Exception as e:
            logger.error(f"❌ 审查图纸 {index} 时发生错误: {e}")
            logger.error(f"   File path: {file_path[:100] if file_path else 'None'}...")
            logger.error(f"   Base64 length: {len(base64_data) if base64_data else 0}")
            logger.error(f"   Image info: {image_info}")
            return [self.create_review_item(
                item_id=f"cad_analysis_error_{index}",
                category="分析错误",
                severity="major",
                description=f"图纸分析失败: {str(e)}",
                suggestion="请检查图纸质量或重新提交"
            )]
    
    def _build_cad_review_prompt(self, image_info: Dict[str, Any], context: Dict[str, Any] = None) -> str:
        """构建CAD审查提示"""
        prompt_parts = [
            "对这张CAD图纸进行专业审查，重点关注以下方面：",
            "",
            "=== 审查要点 ===",
            "1. 图纸类型识别（总平面图、建筑平面图、立面图、剖面图等）",
            "2. 图纸完整性（标题栏、图例、比例尺、标注等）",
            "3. 制图规范性（线型、字体、符号使用规范性）",
            "4. 尺寸标注（完整性、准确性、清晰度）",
            "5. 设计合理性（布局、比例、功能分区）",
            "6. 技术质量（清晰度、准确性、可读性）",
            "7. 与城市更新要求的符合性",
            "",
            "=== 特别关注 ===",
            "- 建筑布局合理性",
            "- 道路交通组织清晰度",
            "- 公共空间和绿化充足性",
            "- 基础设施配套完善性",
            "- 消防通道和安全出口明确性",
            "- 无障碍设施考虑情况",
        ]
        
        # 添加图纸元数据信息
        if image_info.get('metadata'):
            metadata = image_info['metadata']
            prompt_parts.extend([
                "",
                "=== 图纸信息 ===",
                f"图纸ID: {image_info.get('element_id', '未知')}",
                f"文件路径: {image_info.get('file_path', '未知')}",
            ])
            
            if isinstance(metadata, dict):
                for key, value in metadata.items():
                    if key not in ['file_path', 'element_id']:
                        prompt_parts.append(f"{key}: {value}")
        
        if context:
            prompt_parts.extend([
                "",
                "=== 项目背景 ===",
                f"项目类型: {context.get('project_type', '城市更新')}",
                f"项目阶段: {context.get('project_stage', '方案设计')}",
            ])
        
        prompt_parts.extend([
            "",
            "按照系统提示中的JSON格式输出详细的审查结果，必须包含详细的评分信息和扣分依据。"
        ])
        
        return "\n".join(prompt_parts)
    
    def _identify_drawing_type(self, image_info: Dict[str, Any]) -> str:
        """识别图纸类型"""
        file_path = image_info.get('file_path', '')
        element_id = image_info.get('element_id', '')
        metadata = image_info.get('metadata', {})
        
        # 基于文件名或元数据识别图纸类型
        text_to_analyze = f"{file_path} {element_id} {str(metadata)}".lower()
        
        drawing_types = {
            '总平面图': ['总平面', 'site plan', 'master plan', '总图'],
            '建筑平面图': ['平面图', 'floor plan', '平面', '层平面'],
            '立面图': ['立面', 'elevation', '外立面'],
            '剖面图': ['剖面', 'section', '断面'],
            '详图': ['详图', 'detail', '节点', '构造'],
            '效果图': ['效果', 'rendering', '透视', '鸟瞰']
        }
        
        for drawing_type, keywords in drawing_types.items():
            if any(keyword in text_to_analyze for keyword in keywords):
                return drawing_type
        
        return '未识别类型'
    
    def _assess_completeness(self, drawing_types: List[str]) -> str:
        """评估图纸完整性"""
        required_types = ['总平面图', '建筑平面图', '立面图']
        missing_types = [t for t in required_types if t not in drawing_types]
        
        if not missing_types:
            return "图纸类型齐全"
        elif len(missing_types) == 1:
            return f"缺少{missing_types[0]}"
        else:
            return f"缺少{len(missing_types)}种必要图纸类型"
    
    def _assess_quality(self, review_items: List[ReviewItem]) -> str:
        """评估图纸质量"""
        if not review_items:
            return "质量良好"
        
        critical_count = sum(1 for item in review_items if item.severity == 'critical')
        major_count = sum(1 for item in review_items if item.severity == 'major')
        
        if critical_count > 0:
            return f"存在{critical_count}个严重问题"
        elif major_count > 2:
            return f"存在{major_count}个重要问题"
        elif major_count > 0:
            return f"存在{major_count}个问题，整体可接受"
        else:
            return "质量良好"
    
    def calculate_confidence(self, review_items: List[ReviewItem]) -> float:
        """计算置信度"""
        return super().calculate_confidence(review_items)
    
    def calculate_detailed_score(self, review_items: List[ReviewItem]) -> dict:
        """计算详细评分"""
        # 初始分数
        scores = {
            "completeness_score": 20,   # 图纸完整性
            "annotation_score": 20,     # 标注规范性
            "scale_score": 15,          # 比例准确性
            "design_score": 20,         # 设计合理性
            "technical_score": 15,      # 技术规范性
            "consistency_score": 10     # 图纸一致性
        }
        
        score_breakdown = []
        
        # 根据问题严重程度扣分
        for item in review_items:
            deduction = 0
            if item.severity == "critical":
                deduction = 5
            elif item.severity == "major":
                deduction = 3
            elif item.severity == "minor":
                deduction = 1
            
            # 根据检查项目类型扣分
            check_item = getattr(item, 'check_item', '完整性')
            if '完整性' in check_item:
                scores["completeness_score"] = max(0, scores["completeness_score"] - deduction)
            elif '标注规范' in check_item:
                scores["annotation_score"] = max(0, scores["annotation_score"] - deduction)
            elif '比例准确' in check_item:
                scores["scale_score"] = max(0, scores["scale_score"] - deduction)
            elif '设计合理' in check_item:
                scores["design_score"] = max(0, scores["design_score"] - deduction)
            elif '技术规范' in check_item:
                scores["technical_score"] = max(0, scores["technical_score"] - deduction)
            elif '图纸一致' in check_item:
                scores["consistency_score"] = max(0, scores["consistency_score"] - deduction)
            else:
                # 默认扣完整性分数
                scores["completeness_score"] = max(0, scores["completeness_score"] - deduction)
            
            score_breakdown.append(f"{item.description}: -{deduction}分 ({item.severity})")
        
        scores["total_score"] = sum(scores.values())
        scores["score_breakdown"] = score_breakdown
        
        return scores